package com.flyan.game.motafx.core.algorithm;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.time.TimerAction;
import com.flyan.game.motafx.component.BattleComponent;
import com.flyan.game.motafx.core.ds.DLinkedList;
import com.flyan.game.motafx.core.enums.EntityTypeEnum;
import com.flyan.game.motafx.core.util.console.ConsoleUtils;
import com.flyan.game.motafx.core.util.sound.SoundUtils;
import javafx.util.Duration;
import lombok.Data;

import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 战斗结果
 *
 * @author flyan
 * @version 1.0
 * @email flyan_by_chenu@sina.com
 * @since 2025/2/5
 */
@Data
public class BattleResult {

    /**
     * 发起攻击者（先攻）
     */
    private final Battler attacker;

    /**
     * 被攻击目标
     */
    private final Battler target;

    /**
     * 是否可战斗
     */
    private boolean canBatter;

    /**
     * 不可战斗原因
     */
    private String notCanBatterReason;

    /**
     * 战斗过程
     */
    private final DLinkedList<Event> process = new DLinkedList<>();

    /**
     * 胜利者
     */
    private Battler winner;

    public BattleResult(Battler attacker, Battler target) {
        this.attacker = attacker;
        this.target = target;
    }

    /**
     * 添加战斗事件
     *
     * @param event 战斗事件
     */
    public void addEvent(Event event) {
        process.addLast(event);
    }

    /**
     * @return 胜利者是否是攻击方
     */
    public boolean winnerIsAttacker() {
        return winner == attacker;
    }

    /**
     * 战斗结果生效
     */
    public void effect() {
        if (!canBatter) {
            return;
        }

        /* 重现战斗事件（重现经典2333） */
        Entity attackAnimateEntity = FXGL.spawn(EntityTypeEnum.ANIMATE_ATTACK.name(),
                target.getEntity().getPosition());
        Iterator<Event> processIt = process.iterator();
        AtomicReference<TimerAction> timerRef = new AtomicReference<>(null);
        var timer = FXGL.run(() -> {
            if (processIt.hasNext()) {
                Event e = processIt.next();
                SoundUtils.play("attack.wav");
                ConsoleUtils.println("%s攻击了%s，造成%d点伤害！剩余生命：%d".formatted(
                        ((EntityTypeEnum) e.getAttacker().getEntity().getType()).getName(),
                        ((EntityTypeEnum) e.getTarget().getEntity().getType()).getName(),
                        e.getDamage(), e.getTargetHp()));
            } else {
                /* 结束攻击动画~ */
                attackAnimateEntity.removeFromWorld();

                /* 将新的生命面板更新到实体上 */
                attacker.effect();
                target.effect();

                /* 战斗结束 */
                attacker.getEntity().getComponent(BattleComponent.class).setAttacking(false);
                target.getEntity().getComponent(BattleComponent.class).setAttacking(false);

                if (timerRef.get() != null) {
                    timerRef.get().expire();
                }
            }
        }, Duration.seconds(0.2));
        timerRef.set(timer);
    }

    /**
     * 战斗事件
     */
    @Data
    public static class Event {

        /**
         * 攻击者
         */
        private Battler attacker;

        /**
         * 被攻击目标
         */
        private Battler target;

        /**
         * 伤害
         */
        private int damage;

        /**
         * 被攻击目标剩余生命
         */
        private int targetHp;

        public Event(Battler attacker, Battler target, int damage, int targetHp) {
            this.attacker = attacker;
            this.target = target;
            this.damage = damage;
            this.targetHp = targetHp;
        }

        public Event(Battler attacker, Battler target, int damage) {
            this(attacker, target, damage, 0);
        }

    }

}
